package ch.ethz.fcl.metrobuzz.controller.gui.twl.frames;

import ch.ethz.fcl.metrobuzz.MBProperty;
import ch.ethz.fcl.metrobuzz.controller.MBController;
import ch.ethz.fcl.metrobuzz.data.MBData;
import ch.ethz.fcl.metrobuzz.render.interchange.InterchangeRender;
import de.matthiasmann.twl.DialogLayout;
import de.matthiasmann.twl.Label;
import de.matthiasmann.twl.ValueAdjusterInt;

public class TimeControlFrame extends MBFrame {
	private MBController control;
	private PeriodValueAdjuster periodVA;
	private TimeValueAdjuster startVA;

	public TimeControlFrame(MBController control) {
		this.control = control;
		super.create(control, "Time");
	}

	@Override
	protected void setLayout() {
		Label startTimeLabel = new Label("Start Time");
		startVA = new TimeValueAdjuster();
		startVA.setTheme("valueadjuster");
		startTimeLabel.setLabelFor(startVA);
		startVA.setMinMaxValue(MBData.TRIP_STRAT_TIME, MBData.ONE_DAY_TIME);
		startVA.setValue(MBData.startTime);

		Label periodLabel = new Label("Period");
		periodVA = new PeriodValueAdjuster();
		periodVA.setTheme("valueadjuster");
		periodLabel.setLabelFor(startVA);
		periodVA.setMinMaxValue(1, 7);
		periodVA.setValue(1);

		DialogLayout.Group hButtonGroup1 = layout.createParallelGroup()
				.addWidget(startTimeLabel).addWidget(periodLabel);
		DialogLayout.Group hButtonGroup2 = layout.createParallelGroup()
				.addWidget(startVA).addWidget(periodVA);
		DialogLayout.Group hButtonGroup = layout
				.createSequentialGroup()
				.addGroup(hButtonGroup1)
				.addGap(DialogLayout.SMALL_GAP, DialogLayout.SMALL_GAP,
						Short.MAX_VALUE).addGroup(hButtonGroup2);

		DialogLayout.Group vButtonGroup1 = layout.createSequentialGroup()
				.addWidget(startTimeLabel).addGap().addWidget(periodLabel);
		DialogLayout.Group vButtonGroup2 = layout
				.createSequentialGroup()
				.addWidget(startVA)
				.addGap(DialogLayout.SMALL_GAP, DialogLayout.SMALL_GAP,
						Short.MAX_VALUE).addWidget(periodVA);
		DialogLayout.Group vButtonGroup = layout.createParallelGroup()
				.addGroup(vButtonGroup1).addGroup(vButtonGroup2);

		layout.setHorizontalGroup(hButtonGroup);
		layout.setVerticalGroup(vButtonGroup);
	}

	public void reset() {
		startVA.setValue(32);
		periodVA.setValue(1);
	}

	public ValueAdjusterInt getStartTimeVA() {
		return startVA;
	}

	public ValueAdjusterInt getPeriodVA() {
		return periodVA;
	}

	public class TimeValueAdjuster extends ValueAdjusterInt {
		@Override
		public void doDecrement() {
			super.doDecrement();

			if (MBData.period != MBData.ONE_DAY_TIME)
				MBData.startTime = this.getValue();

			if (MBData.period + MBData.startTime > MBData.ONE_DAY_TIME) {
				MBData.startTime = MBData.TRIP_STRAT_TIME;
				MBData.period = MBData.ONE_DAY_TIME - MBData.TRIP_STRAT_TIME;
			}
			if (MBProperty.MRT || MBProperty.REGIONS) {
				InterchangeRender.UPDATE = true;
				MBData.TIME_CHANGED = true;
			}
			if (MBProperty.ACCESSIBILITY) {
				control.getContainer().getRender().getAccessibilityRender()
						.update();
			}
		}

		@Override
		public void doIncrement() {
			super.doIncrement();

			if (MBData.period != MBData.ONE_DAY_TIME)
				MBData.startTime = this.getValue();

			if (MBData.period + MBData.startTime > MBData.ONE_DAY_TIME) {
				MBData.startTime = MBData.TRIP_STRAT_TIME;
				MBData.period = MBData.ONE_DAY_TIME - MBData.TRIP_STRAT_TIME;
			}

			if (MBProperty.MRT || MBProperty.REGIONS) {
				InterchangeRender.UPDATE = true;
				MBData.TIME_CHANGED = true;
			}
			if (MBProperty.ACCESSIBILITY) {
				control.getContainer().getRender().getAccessibilityRender()
						.update();
			}

		}

		@Override
		public String formatText() {
			int value = this.getValue();
			int hour = value / 4;
			String sh = hour + "";
			if (hour < 10)
				sh = "0" + sh;
			int min = value % 4 * 15;
			String sm = min + "";
			if (min == 0)
				sm = "0" + sm;
			return sh + ":" + sm;
		}

		@Override
		public String validateEdit(String text) {
			String warning = "Enter a value between [0, 96]:\n"
					+ "0:   00:00\n" + "1:   00:15\n" + "...\n"
					+ "95:   23:45\n" + "96:   24:00";
			try {
				int value = Integer.parseInt(text);
				if (value >= this.getMinValue() && value <= this.getMaxValue())
					return null;
				else
					return warning;
			} catch (NumberFormatException e) {
				return warning;
			}
		}
	}

	public class PeriodValueAdjuster extends ValueAdjusterInt {
		@Override
		public void doDecrement() {
			super.doDecrement();
			MBData.period = this.getPeriodValue();
			if (MBData.period + MBData.startTime > MBData.ONE_DAY_TIME) {
				MBData.startTime = MBData.TRIP_STRAT_TIME;
				MBData.period = MBData.ONE_DAY_TIME - MBData.TRIP_STRAT_TIME;
			} else
				MBData.startTime = startVA.getValue();
			if (MBProperty.MRT || MBProperty.REGIONS) {
				InterchangeRender.UPDATE = true;
				MBData.TIME_CHANGED = true;
			}
			if (MBProperty.ACCESSIBILITY) {
				control.getContainer().getRender().getAccessibilityRender()
						.update();
			}
		}

		@Override
		public void doIncrement() {
			super.doIncrement();
			MBData.period = this.getPeriodValue();
			if (MBData.period + MBData.startTime >= MBData.ONE_DAY_TIME) {
				MBData.startTime = MBData.TRIP_STRAT_TIME;
				MBData.period = MBData.ONE_DAY_TIME - MBData.TRIP_STRAT_TIME;
			} else
				MBData.startTime = startVA.getValue();

			if (MBProperty.MRT || MBProperty.REGIONS) {
				InterchangeRender.UPDATE = true;
				MBData.TIME_CHANGED = true;
			}
			if (MBProperty.ACCESSIBILITY) {
				control.getContainer().getRender().getAccessibilityRender()
						.update();
			}
		}

		private int getPeriodValue() {
			int value = this.getValue();
			switch (value) {
			case 1:
				return 1;
			case 2:
				return 2;
			case 3:
				return 3;
			case 4:
				return 4;
			case 5:
				return 8;
			case 6:
				return 16;
			case 7:
				return MBData.ONE_DAY_TIME - MBData.TRIP_STRAT_TIME;
			default:
				return 1;
			}
		}

		@Override
		public String formatText() {
			int value = this.getValue();
			switch (value) {
			case 1:
				return 15 + " min";
			case 2:
				return 30 + " min";
			case 3:
				return 45 + " min";
			case 4:
				return 1 + " h";
			case 5:
				return 2 + " h";
			case 6:
				return 4 + " h";
			case 7:
				return 24 + " h";
			default:
				return 15 + " min";
			}
		}

		@Override
		public String validateEdit(String text) {
			String warning = "Enter one of these:\n" + "\t1:   15 min \n"
					+ "\t2:   30 min \n" + "\t3:   45 min \n" + "\t4:   1 h \n"
					+ "\t5:   2 h \n" + "\t6:   4 h \n" + "\t7:   24 h";
			try {
				int value = Integer.parseInt(text);
				if (value >= this.getMinValue() && value <= this.getMaxValue())
					return null;
				else
					return warning;
			} catch (NumberFormatException e) {
				return warning;
			}
		}
	}
}
